package top.lyunk.demo.server.a;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import io.seata.core.context.RootContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.lyunk.demo.server.a.mapper.User;
import top.lyunk.demo.server.a.mapper.UserMapper;
import top.lyunk.demo.server.b.entity.Student;
import top.lyunk.demo.server.b.rpc.dubbo.dubbo.ServerBDubboAPI;

@Slf4j
@RefreshScope
@Service
public class ServerAService {

    @Value("${test-user.id}")
    private Long testUserId;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ServerBDubboAPI serverBDubboAPI;

    @SentinelResource(value = "getTestUserId", blockHandler = "exceptionHandler", fallback = "configTestUserIdFallback")
    public Long getTestUserId() {
        return testUserId;
    }

    public Long configTestUserIdFallback(Throwable e) {
        e.printStackTrace();
        return -1L;
    }

    // Block 异常处理函数，参数最后多一个 BlockException，其余与原函数一致.
    public String exceptionHandler(long s, BlockException ex) {
        // Do some log here.
        ex.printStackTrace();
        return "Oops, error occurred at " + s;
    }

    @Transactional
    @ShardingSphereTransactionType(TransactionType.BASE)
    public int addUser(long id, String name, Integer age, boolean error) {
        log.info("globalTransactional begin, Xid:{}", RootContext.getXID());

        userMapper.insert(new User().setId(id).setName(name).setAge(age));
        serverBDubboAPI.addStudent(new Student().setId(id).setName(name));

        //异常模拟
        if (error) {
            int i = 1 / 0;
        }
        return 1;
    }

}
